package com.hot12345.server.DBConnection;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
  
  
public class PoolConfiguer {
 
	private static Map libraryMap=null;
	
 
	private static Log logger = LogFactory.getLog(PoolConfiguer.class);
	private static Object lock = new Object();

	private   void loadAll() {
		if (libraryMap == null) {
			try {
				java.net.URL url = Thread.currentThread()
						.getContextClassLoader().getResource("config/pool-config.xml");
			 File propertyFile = new File(url.getFile());
			// File propertyFile = new File("D:/www/search/index/bbs2/config/pool-config.xml");
				libraryMap = new HashMap(2);    
				ConfigeFile[] configeFiles=process(propertyFile);
				for(int i=0;i<configeFiles.length;i++){
					libraryMap.put(configeFiles[i].getPoolName(),configeFiles[i]);
				}
				 
			} catch (Exception ex) {
				  try {
					    String filepath=ClassLoader.getSystemResource("").getPath();
					     System.out.println(filepath);
					    File propertyFile = new File(filepath+"config/pool-config.xml");
						libraryMap = new HashMap(2);  
						ConfigeFile[] configeFiles=process(propertyFile);
						for(int i=0;i<configeFiles.length;i++){
							libraryMap.put(configeFiles[i].getPoolName(),configeFiles[i]);
						}
					    } catch (Exception e) {
					     // TODO Auto-generated catch block
					     throw new RuntimeException("read pool-pool.properties faile!");
					    }  
			}

		}
	}

 
	public static ConfigeFile getConfigeFile(String poolName) {
		
		if (libraryMap == null) {
			synchronized (lock) {
				if (libraryMap == null) {
					PoolConfiguer poolConfiguer=new PoolConfiguer();
					poolConfiguer.loadAll();
				}
			}
		} 
		
		return (ConfigeFile)libraryMap.get(poolName);
	}
	
	/**
	 *  
	 * @param file
	 * @return
	 */
	 private ConfigeFile[]  process(File file){
	 
		 DOMParser xmlParser = new DOMParser();
		 try {
			xmlParser.parse(file.getAbsolutePath());
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			logger.error("SAXException",e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error("IOException",e);
		}
	        Document dom = xmlParser.getDocument();

	        NodeList nodeList = dom.getElementsByTagName("pool");
	        ConfigeFile[] configs = new ConfigeFile[nodeList.getLength()];
	        for (int i=0; i<nodeList.getLength(); i++) {
	            Node node = nodeList.item(i);
	            configs[i] = getPoolConfig(node);
	        }
	      //  validatePoolConfigs(configs);
	       // return configs;
		 return configs;
	 }
	 
	 
	    private ConfigeFile getPoolConfig(Node node)  {
	         ConfigeFile configFile = new ConfigeFile();
	        NodeList list = node.getChildNodes();
	        for (int i=0; i<list.getLength(); i++) {
	            Node childNode = list.item(i);
	            String nodeName = childNode.getNodeName();
	            if (nodeName != null && nodeName.equals("basic")) {
	                populateBasic(configFile, childNode);
	            }
	            if (nodeName != null && nodeName.equals("connect-strings")) {
	                populateConnectString(configFile, childNode);
	            }
	            if (nodeName != null && nodeName.equals("pool-sizing")) {
	                populatePoolSizing(configFile, childNode);
	            }
	            if (nodeName != null && nodeName.equals("leak-detection")) {
	               // populateLeakDetection(configFile, childNode);
	            }
	            if (nodeName != null && nodeName.equals("external-pooling")) {
	              //  populateExternalPooling(configFile, childNode);
	            }
	        }
	        return configFile;

	    }
	    
	    private void populatePoolSizing(ConfigeFile config, Node node) {

	        NodeList list = node.getChildNodes();
	        for (int i=0; i<list.getLength(); i++) {
	            Node childNode = list.item(i);
	            String nodeName = childNode.getNodeName();
	            if (nodeName != null) {
	                if (nodeName.equals("min-connections")) {
	                    config.setMinConnections(Integer.valueOf(getTagValue(childNode)).intValue());
	                }
	                if (nodeName.equals("max-connections")) {
	                    config.setMaxConnections(Integer.valueOf(getTagValue(childNode)).intValue());
	                }
	                if (nodeName.equals("increment-by")) {
	                    config.setIncrement(Integer.valueOf(getTagValue(childNode)).intValue());
	                }
	                if (nodeName.equals("increment-by")) {
	                    config.setIncrement(Integer.valueOf(getTagValue(childNode)).intValue());
	                }
	                if (nodeName.equals("max-free-connections-for-release")) {
	                //    config.setMaxConnectionsForRelease(Integer.valueOf(getTagValue(childNode)).intValue());
	                }
	                if (nodeName.equals("connection-wait-time-out")) {
	                //    config.setConnectionWaitTimeOut(Integer.valueOf(getTagValue(childNode)).intValue()); 
	                }
	                if (nodeName.equals("max-connection-idle-time")) {
	                //    config.setMaxConnectionIdleTime(Integer.valueOf(getTagValue(childNode)).intValue());
	                }
	            }
	        }
	    }
	    
	    private void populateConnectString(ConfigeFile config, Node node)  {

	        NodeList list = node.getChildNodes();
	        List connList = new ArrayList();
             
	        for (int i=0; i<list.getLength(); i++) {
	        Node childNode = list.item(i);
	        String nodeName = childNode.getNodeName();	         
	        if (nodeName != null) {
                if (nodeName.equals("connect-string")) {
                	 config.setDriverUrl(getTagValue(childNode));
                	 break; 
                }
	        }   
	        }
                 
//	        for (int i=0; i<list.getLength(); i++) {
//	            Node childNode = list.item(i);
//	            String nodeName = childNode.getNodeName();
//	            if (nodeName != null) {
//	                if (nodeName.equals("connect-string")) {
//	                    PoolConfig.ConnectionString connectString = new PoolConfig.ConnectionString();
//
//	                  connectString.setConnectString(getTagValue(childNode));
//	                    connectString.setName(config.getPoolName() + "." + getAttributeValue(childNode, "name"));
//	                   connList.add(connectString);
//	                }
//	                if (nodeName.equals("thread-stickiness")) {
//	                  config.setThreadStickiness(Boolean.valueOf(getTagValue(childNode)));
//	                }
//	            }
//	        }
//	       config.setDriverUrl((PoolConfig.ConnectionString[])connList.toArray(new PoolConfig.ConnectionString[connList.size()])[0]);

	    }
	    
	    private void populateBasic(ConfigeFile config, Node node) {


	        NodeList list = node.getChildNodes();
	        for (int i=0; i<list.getLength(); i++) {
	            Node childNode = list.item(i);
	            String nodeName = childNode.getNodeName();
	            if (nodeName != null) {
	                if (nodeName.equals("pool-name")) {	                
	                    config.setPoolName(getTagValue(childNode));
	                }
	                if (nodeName.equals("default-pool")) {
	                  //  config.setDefaultPool(Boolean.valueOf(getTagValue(childNode)));
	                }
	                if (nodeName.equals("connection-driver")) {
	                    config.setDriver_class(getTagValue(childNode));
	                }
	                if (nodeName.equals("username")) {
	                    config.setUserName(getTagValue(childNode));
	                }
	                if (nodeName.equals("password")) {
	                    config.setPassword(getTagValue(childNode));
	                }
	                if (nodeName.equals("auto-close")) {
	                  //  config.setAutoClose(Boolean.valueOf(getTagValue(childNode)));
	                }
	                if (nodeName.equals("allow-anonymous-connections")) {
	                  //  config.setAllowAnonymousConnections(Boolean.valueOf(getTagValue(childNode)));
	                }
	                if (nodeName.equals("validator-query")) {
	                 //   config.setValidatorQuery(getTagValue(childNode));
	                }
	            }
	        }

	    }
	    
	    private String getTagValue(Node nod) {

	        // Some crazy xml hack
	        if (nod.getChildNodes() != null && nod.getChildNodes().getLength() != 0)
	            return nod.getChildNodes().item(0).getNodeValue();
	        else
	            return nod.getNodeValue();

	    }

	    
	    private String getAttributeValue(Node nod, String attrName) throws  Exception {

	        // Some crazy xml hack
	        NamedNodeMap map = nod.getAttributes();
	        Node attrNode = map.getNamedItem(attrName);
	        if (attrNode == null)
	        	//return null;
	           throw new  Exception ("Attribute '" + attrName + "' of node '" + nod.getNodeName() + "' is null");
	        return attrNode.getNodeValue();
  
	    }
	/**
	 * test
	 * @param args  
	 */  
	public static void main(String[] args){
		 System.out.println("CCCCCCCC"+PoolConfiguer.getConfigeFile("culture").getDriverUrl());
		 System.out.println("getDriver_class"+PoolConfiguer.getConfigeFile("culture").getDriver_class());
		 System.out.println("getPassword"+PoolConfiguer.getConfigeFile("culture").getPassword());
		 System.out.println("getUserName"+PoolConfiguer.getConfigeFile("culture").getUserName());
		  
	}
}
